const jsonp = (opts) => {
    return new Promise((resolve, reject) => {
        try {
            const {
                url,
                params,
                callback = "callback",
            } = opts || {};
            let script = null;
            // 基于 callback name 在全局挂载对应的函数
            window[callback] = function (res) {
                resolve(res);
                if(!script) script.parentNode.removeChild(script);
            };
            // 拼接参数字符串以及 callback name 到 url 中去
            let hasParams = url.includes("?");
            let _url = `${url}${hasParams ? "&": "?"}callback=${callback}`;
            let paramString = '';
            for (const key in params) {
                if (Object.hasOwnProperty.call(params, key)) {
                    const value = params[key];
                    paramString += `${key}=${value}&`;
                }
            }
            paramString = paramString.slice(0, paramString.length - 1);
            hasParams = _url.includes("?");
            _url = `${_url}${hasParams ? "&": "?"}${paramString}`;
            // 动态创建 script 标签
            script = document.createElement("script");
            // script 引用
            script.setAttribute("src", _url);
            // script 被添加到页面(已经开始向服务端发起请求了)
            document.head.appendChild(script);
        } catch (error) {
            console.log(error);
            reject(error);
        }
    })
};